package com.menggudf.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.menggudf.model.request.DsRequest;
import com.menggudf.model.response.AskResult;
import com.menggudf.model.response.DsReponse;
import com.menggudf.model.response.Question;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Controller
@RequestMapping("deepseek2")
public class DeepSeek2Controller {


    @RequestMapping(value = "askDs",method = RequestMethod.POST,consumes = "application/json")
    @org.springframework.web.bind.annotation.ResponseBody
    public Object askDs(@org.springframework.web.bind.annotation.RequestBody DsRequest dsRequest) throws IOException {

        String tip = "<instruction>\n" +
                //"我们来模拟一段医生与患者的对话。你扮演诊所医生的角色，根据患者提供的主诉症状进行问诊，考虑到患者都是没有医学知识，请以通俗易懂的术语进行问诊。以下<example></example>是我的提供的完整示例，请按照以下步骤操作：\n" +
                "假设你是一位\n" +
                "1.在中国和美国都受到过顶级医学院校博士教育课程的，\n" +
                "2.具有三十年临床经验的，\n" +
                "3.定期跟踪最新全球权威医学杂志的，熟悉近十五年美国，英国，中国，日本，德国，法国，西班牙权威医学杂志，\n" +
                "4.熟悉近十五年sci医学类权威杂志，\n" +
                "5.熟悉全球各国罕见病医学杂志的医生。" +
                "我来找你看病，我们俩来模拟一段医学对话。" +
                "A.我给出主诉后\n" +
                "B.根据我的回答，你通过不断的继续提问题，让我用是或者否来回答，\n" +
                "C.你根据我的回答再进一步提问，\n" +
                "D.通过问诊，仔细分别我的诊断，通过不断的鉴别诊断得出最精确的诊断和其他可疑的鉴别诊断，\n" +
                "E.提出需要做检查和化验，\n" +
                "F.并按照该疾病中国和美国最新的临床诊疗指南，给出及时的用药治疗方案，\n" +
                "G.同时要注意问到是否有药物过敏情况和用药注意事项，" +
                "在诊疗过程中要牢记采用腹痛黄金法则，胸痛黄金法则，头痛黄金法则，对话采用你提问我回答的方式而不是你的自问自答，\n" +
                "再补充一点，就是在诊疗过程，要时刻留意这一主诉是否是某疾病过程中的某一阶段或者是早期并不太明显的时期，要注意区别。\n" +
                "还需要提问患者的性别年龄，既往史和个人史，如果是女性还需要提问月经史" +
                "\n" +
                "1. 初始阶段：\n" +
                "   - 接收患者的主诉症状：{{patient_complaint}}\n" +
                "   - 根据主诉生成3-5个鉴别诊断方向\n" +
                "\n" +
                "2. 问诊阶段：\n" +
                "   - 针对每个鉴别诊断方向提出具体问题\n" +
                "   - 每个问题使用以下JSON格式（需要能使用com.alibaba.fastjson格式化）：\n" +
                "     [{\"question\": \"<问题文本>\",{\"Keywords\":\"<问题关键词>\"}, \"answer\": [\"<可选答案1>\", \"<可选答案2>\"]}]\n" +
                "   - 涉及身体部位的问题需列举相关部位\n" +
                "   - 涉及时间的问题需提供具体时间选项\n" +
                "   - 不要提问上述已经提问过相同内容的问题\n" +
                "   - 考虑到患者都是没有医学知识，请以通俗易懂的术语进行问诊\n" +
                "\n" +
                "3. 终止条件：\n" +
                "   - 当患者说\"暂无更多病症\"时结束问诊\n" +
                "\n" +
                "4. 诊断阶段：\n" +
                "   - 给出最可能的1种诊断和2种可能的鉴别诊断\n" +
                "   - 使用以下SJON格式（需要能使用com.alibaba.fastjson格式化）返回诊断信息：\n" +
                "     {\n" +
                "       \"diagnostic_check\": [\"<检查项目1>\", \"<检查项目2>\"],\n" +
                "       \"laboratory_item\": [\"<化验项目1>\", \"<化验项目2>\"],\n" +
                "       \"medical\": \"<临时药物>\",\n" +
                "       \"diagnostic\": \"<诊疗方案>\",\n" +
                "       \"tips\": \"<注意事项>\"\n" +
                "     }\n" +
                "\n" +
                "注意事项：\n" +
                "- 所有输出必须为纯文本，不要包含任何XML标签\n" +
                "- 问题要具体且有鉴别诊断价值\n" +
                "- 给出的检查项目和化验项目应与诊断相关\n" +
                "- 临时药物要注明用法用量\n" +
                "- 注意事项要具体实用\n" +
                "- 每一次提问只能返回初始阶段或者诊断阶段的结果\n" +
                "- 当用户单独输入\"暂无更多病症\"时才可以进入诊断阶段，返回诊断信息\n" +
                "- 返回的报文体用到的标点符号全部都要使用半角英文符号\n" +
                "\n" +
                "<example>\n" +
                "患者主诉：\"我头痛三天了\"\n" +
                "\n" +
                "医生输出：\n" +
                "[\n" +
                "  {\"question\": \"头痛的具体部位是哪里？（可选：前额、后脑、太阳穴、全头）\",\"Keywords\":\"头痛的部位\", \"answer\": [\"头痛的具体部位是前额\",\"头痛的具体部位是后脑\",\"头痛的具体部位是太阳穴\",\"头痛的具体部位是全头\"],\n" +
                "  {\"question\": \"头痛的性质是？(胀痛/刺痛/搏动性疼痛/紧缩感)\",\"Keywords\":\"头痛的性质\", \"answer\": [\"头痛的性质是胀痛\", \"头痛的性质是刺痛\", \"头痛的性质是搏动性疼痛\", \"头痛的性质是紧缩感\"],\n" +
                "  {\"question\": \"是否伴随其他症状？（可选：恶心/呕吐、畏光/畏声、视力模糊、肢体无力）\",\"Keywords\":\"伴随的症状\", \"answer\": [\"伴随恶心/呕吐\",\"伴随畏光/畏声\"，\"伴随视力模糊，伴随肢体无力\",\"没有其它症状了\"],\n" +
                "  {\"question\": \"头痛持续了多长时间？（可选：小于1小时、1-24小时、1-3天、3天以上）\",\"Keywords\":\"头痛多长时间\", \"answer\": [\"头痛持续了小于1小时\",\"头痛持续了1-24小时\",\"头痛持续了1-3天\",\"头痛持续了3天以上\"],\n" +
                "  {\"question\": \"近期是否有头部外伤史或高血压病史？\",\"Keywords\":\"外伤史或高血压病史\", \"answer\": [\"否认近期有头部外伤史或高血压病史\",\"承认近期有头部外伤史或高血压病史\"],\"answerBak\" : [\"\",\"\"],\"subject\" :\"\"},\n" +
                "  {\"question\": \"皮肤瘙痒的具体部位是哪里？（可选：全身、四肢、躯干、面部、手足）\",\"Keywords\":\"皮肤瘙痒的部位\", \"answer\": [\"皮肤瘙痒的具体部位是全身\",\"皮肤瘙痒的具体部位是四肢\",\"皮肤瘙痒的具体部位是躯干\",\"皮肤瘙痒的具体部位是面部\",\"皮肤瘙痒的具体部位是手足\"]},\n" +
                "  {\"question\": \"是否有闪光感或视野缺损？\",\"Keywords\":\"闪光感或视野缺损\", \"answer\": [\"有闪光感或视野缺损\",\"没有闪光感或视野缺损\"]}\n" +
                "]\n" +
                "\n" +
                "当患者说\"暂无更多病症\"后：\n" +
                "{\n" +
                "  \"diagnostic_check\": [\"头颅CT\", \"血压监测\"],\n" +
                "  \"laboratory_item\": [\"血常规\", \"电解质\"],\n" +
                "  \"medical\": \"布洛芬200mg 必要时每6小时一次\",\n" +
                "  \"diagnostic\": \"偏头痛可能性大，需排除紧张性头痛和颅内病变\",\n" +
                "  \"tips\": \"避免劳累和强光刺激，若出现剧烈呕吐或意识改变立即就诊\"\n" +
                "}\n" +
                "</example>\n" +
                "</instruction>";
        DsRequest.Messages messages = new DsRequest.Messages();
        messages.setContent(tip);
        messages.setRole("user");
        List<DsRequest.Messages> messagesList = new ArrayList<>();
        messagesList.add(messages);
        messagesList.addAll(dsRequest.getMessages());

        dsRequest.setMessages(messagesList);
        OkHttpClient client = new OkHttpClient().newBuilder().connectTimeout(100, TimeUnit.MINUTES)
                .readTimeout(100,TimeUnit.MINUTES)
                .build();
        MediaType mediaType = MediaType.parse("application/json");
        String content = JSON.toJSONString(dsRequest);
        RequestBody body = RequestBody.create(mediaType,content);
        Request request = new Request.Builder()
                .url("https://api.deepseek.com/chat/completions")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .addHeader("Authorization", "Bearer sk-f1e8b263255748279893110ddd201da0")
                .build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            String responseContent = response.body().string();
            DsReponse dsReponse = JSON.parseObject(responseContent, DsReponse.class);
            String askResultText = dsReponse.getChoices().get(0).getMessage().getContent().replaceAll("```json","").replaceAll("```","").replaceAll("，",",");
            if(!dsRequest.getStopFlag() && askResultText.contains("当患者说\"暂无更多病症\"后：")){
                String[] splitContent = askResultText.split("当患者说\"暂无更多病症\"后：");
                askResultText = splitContent[0];
            }
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode node = objectMapper.readTree(askResultText);

            if(dsRequest.getStopFlag() || !node.isArray()){
                return JSON.parseObject(askResultText, AskResult.class);
            }else if(CollectionUtils.isNotEmpty(dsReponse.getChoices())){
                List<Question> questions = JSONArray.parseArray(askResultText, Question.class);
                log.info(JSON.toJSONString(questions));
                return questions;
            }
            return dsReponse;
        }catch (IOException e){
            log.error("askDs errot",e);
        }catch (JSONException e1){
            log.error("json格式化出现错误：" ,e1);
        }catch (Exception e) {
            log.error("出现错误：" ,e);
            throw new RuntimeException(e);
        }
        return null;
    }

    public static void main(String[] args) {
        String str = "[{\"answer\":\"[\"头痛的具体部位是前额\",\"头痛的具体部位是后脑\",\"头痛的具体部位是太阳穴\",\"头痛的具体部位是全头\"]\",\"question\":\"头痛的具体部位是哪里？（可选：前额、后脑、太阳穴、全头）\"},{\"answer\":\"[\"头痛的性质是胀痛\",\"头痛的性质是刺痛\",\"头痛的性质是搏动性疼痛\",\"头痛的性质是紧缩感\"]\",\"question\":\"头痛的性质是？(胀痛/刺痛/搏动性疼痛/紧缩感)\"},{\"answer\":\"[\"伴随恶心/呕吐\",\"伴随畏光/畏声\",\"伴随视力模糊\",\"伴随肢体无力\",\"没有其它症状了\"]\",\"question\":\"是否伴随其他症状？（可选：恶心/呕吐、畏光/畏声、视力模糊、肢体无力）\"},{\"answer\":\"[\"头痛持续了小于1小时\",\"头痛持续了1-24小时\",\"头痛持续了1-3天\",\"头痛持续了3天以上\"]\",\"question\":\"头痛持续了多长时间？（可选：小于1小时、1-24小时、1-3天、3天以上）\"},{\"answer\":\"[\"否认近期有头部外伤史或高血压病史\",\"承认近期有头部外伤史或高血压病史\"]\",\"question\":\"近期是否有头部外伤史或高血压病史？\"}]";


    }


}
